Skip to contentMethod: resolveOntologyPrefixes(OWLOntology, String, RemotePrefixResolver)
1: /*
2: * JOPA
3: * Copyright (C) 2024 Czech Technical University in Prague
4: *
5: * This library is free software; you can redistribute it and/or
6: * modify it under the terms of the GNU Lesser General Public
7: * License as published by the Free Software Foundation; either
8: * version 3.0 of the License, or (at your option) any later version.
9: *
10: * This library is distributed in the hope that it will be useful,
11: * but WITHOUT ANY WARRANTY; without even the implied warranty of
12: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13: * Lesser General Public License for more details.
14: *
15: * You should have received a copy of the GNU Lesser General Public
16: * License along with this library.
17: */
18: package cz.cvut.kbss.jopa.owl2java.prefix;
19:
20: import cz.cvut.kbss.jopa.owl2java.config.TransformationConfiguration;
21: import cz.cvut.kbss.jopa.owl2java.exception.OWL2JavaException;
22: import cz.cvut.kbss.jopa.vocabulary.DC;
23: import cz.cvut.kbss.jopa.vocabulary.OWL;
24: import cz.cvut.kbss.jopa.vocabulary.RDF;
25: import cz.cvut.kbss.jopa.vocabulary.RDFS;
26: import cz.cvut.kbss.jopa.vocabulary.SKOS;
27: import org.semanticweb.owlapi.model.AxiomType;
28: import org.semanticweb.owlapi.model.IRI;
29: import org.semanticweb.owlapi.model.OWLAnnotationProperty;
30: import org.semanticweb.owlapi.model.OWLDataFactory;
31: import org.semanticweb.owlapi.model.OWLDataProperty;
32: import org.semanticweb.owlapi.model.OWLOntology;
33: import org.semanticweb.owlapi.model.OWLOntologyManager;
34: import org.slf4j.Logger;
35: import org.slf4j.LoggerFactory;
36:
37: import java.io.File;
38: import java.io.IOException;
39: import java.nio.charset.StandardCharsets;
40: import java.nio.file.Files;
41: import java.util.Collections;
42: import java.util.HashMap;
43: import java.util.List;
44: import java.util.Map;
45: import java.util.Objects;
46: import java.util.Optional;
47: import java.util.concurrent.ConcurrentHashMap;
48:
49: /**
50: * Keeps a map of prefixes resolved from provided ontologies.
51: * <p>
52: * Prefixes are resolved using the following strategy:
53: * <ul>
54: * <li>If an ontology has an explicitly specified prefix (using the configured prefix property), it is used</li>
55: * <li></li>
56: * </ul>
57: */
58: public class PrefixMap {
59:
60: private static final Logger LOG = LoggerFactory.getLogger(PrefixMap.class);
61:
62: /**
63: * Map ontology IRI -> prefix
64: */
65: private final Map<String, String> prefixes;
66:
67: public PrefixMap(OWLOntologyManager ontologyManager, TransformationConfiguration config) {
68: this.prefixes = resolvePrefixes(Objects.requireNonNull(ontologyManager), config);
69: }
70:
71: /**
72: * Resolves prefixes of ontologies accessible from the specified ontology manager.
73: *
74: * @param ontologyManager Manager of ontologies to process
75: */
76: private Map<String, String> resolvePrefixes(OWLOntologyManager ontologyManager,
77: TransformationConfiguration config) {
78: final Map<String, String> result = new ConcurrentHashMap<>(builtInPrefixes());
79: ontologyManager.ontologies().parallel().filter(o -> o.getOntologyID().isNamed()).forEach(o -> {
80: assert o.getOntologyID().getOntologyIRI().isPresent();
81: result.putAll(resolveOntologyPrefixes(o, config.getOntologyPrefixProperty(), config.getRemotePrefixResolver()));
82: });
83: result.putAll(resolvePrefixesFromPrefixMappingFile(config.getPrefixMappingFile()));
84: LOG.debug("Resolved prefix map: {}", result);
85: return result;
86: }
87:
88: private static Map<String, String> resolveOntologyPrefixes(OWLOntology ontology, String prefixProperty,
89: RemotePrefixResolver remotePrefixResolver) {
90: final Map<String, String> result = new HashMap<>();
91: final OWLDataFactory df = ontology.getOWLOntologyManager().getOWLDataFactory();
92: final OWLAnnotationProperty annProperty = df.getOWLAnnotationProperty(prefixProperty);
93:• assert ontology.getOntologyID().getOntologyIRI().isPresent();
94: final IRI ontologyIri = ontology.getOntologyID().getOntologyIRI().get();
95: ontology.axioms(AxiomType.ANNOTATION_ASSERTION)
96: .filter(ax -> ax.getProperty().equals(annProperty) && ax.getValue().isLiteral() && ax.getSubject()
97: .isIRI())
98: .forEach(ax -> {
99: assert ax.getSubject().asIRI().isPresent();
100: assert ax.getValue().asLiteral().isPresent();
101:
102: result.put(ax.getSubject().asIRI().get().getIRIString(), ax.getValue().asLiteral().get()
103: .getLiteral());
104: });
105: final OWLDataProperty dataProperty = df.getOWLDataProperty(prefixProperty);
106: ontology.axioms(AxiomType.DATA_PROPERTY_ASSERTION)
107: .filter(ax -> ax.getProperty().equals(dataProperty) && ax.getSubject().isIndividual())
108: .forEach(ax -> result.put(ax.getSubject().asOWLNamedIndividual().toStringID(), ax.getObject()
109: .getLiteral()));
110:• if (!result.containsKey(ontologyIri.getIRIString())) {
111: remotePrefixResolver.resolvePrefix(ontologyIri).ifPresent(p -> result.put(ontologyIri.getIRIString(), p));
112: }
113: return result;
114: }
115:
116: private static Map<String, String> resolvePrefixesFromPrefixMappingFile(String mappingFilePath) {
117: if (mappingFilePath == null) {
118: return Collections.emptyMap();
119: }
120: final File file = new File(mappingFilePath);
121: try {
122: LOG.debug("Loading prefix mapping from file '{}'.", file);
123: final List<String> lines = Files.readAllLines(file.toPath(), StandardCharsets.UTF_8);
124: final Map<String, String> prefixMap = new HashMap<>(lines.size());
125: lines.stream().filter(line -> !line.isBlank()).forEach(line -> {
126: final String[] mapping = line.split("=");
127: if (mapping.length != 2) {
128: LOG.warn("Mapping line '{}' does not correspond to the expected pattern '$namespace=$prefix'. Skipping it.", line);
129: }
130: prefixMap.put(mapping[0], mapping[1]);
131: });
132: return prefixMap;
133: } catch (IOException e) {
134: LOG.error("Unable to read prefix mapping file.", e);
135: throw new OWL2JavaException("Unable to read prefix mapping file.", e);
136: }
137: }
138:
139: /**
140: * Gets prefix for an ontology with the specified IRI.
141: *
142: * @param ontologyIri Ontology IRI
143: * @return Resolved prefix, if available
144: */
145: public Optional<String> getPrefix(IRI ontologyIri) {
146: Objects.requireNonNull(ontologyIri);
147: return Optional.ofNullable(prefixes.get(ontologyIri.getIRIString()));
148: }
149:
150: /**
151: * Checks whether a prefix has been resolved for the specified ontology IRI.
152: *
153: * @param ontologyIri Ontology IRI
154: * @return {@code true} if a prefix is registered for the ontology IRI, {@code false} otherwise
155: */
156: public boolean hasPrefix(IRI ontologyIri) {
157: Objects.requireNonNull(ontologyIri);
158: return prefixes.containsKey(ontologyIri.getIRIString());
159: }
160:
161: private static Map<String, String> builtInPrefixes() {
162: return Map.of(
163: RDF.NAMESPACE, RDF.PREFIX,
164: RDFS.NAMESPACE, RDFS.PREFIX,
165: OWL.NAMESPACE, OWL.PREFIX,
166: SKOS.NAMESPACE, SKOS.PREFIX,
167: DC.Terms.NAMESPACE, "dcterms"
168: );
169: }
170: }